<?php
/**
 * Created by PhpStorm.
 * Author: QinShuai
 * Email: qinshuai0423@qq.com
 * Date: 2021/6/11
 */

namespace backend\controllers;

use backend\behaviors\AdminAuthBehavior;
use backend\behaviors\AdminLogBehavior;
use backend\models\AdminRule;
use Yii;
use yii\db\Query;
use yii\web\Controller;
use yii\filters\AccessControl;
use yii\web\Response;
use yii\helpers\ArrayHelper;

class BaseController extends Controller
{
    /**
     * 传递到页面参数
     * @var
     */
    public $data;
    /**
     * 关闭csrf验证
     * @var bool
     */
    public $enableCsrfValidation = false;
    /**
     * 模型（用于指定模型）
     * @var
     */
    public $_model;

    /**
     * @return array
     */
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::class,
                'rules' => [
                    [
                        'allow' => true,
                        'roles' => ['@'], // 登录
                    ],
                ],
            ],
            'adminLog' => [
                'class' => AdminLogBehavior::class,
            ],
            'auth' => [
                'class' => AdminAuthBehavior::class
            ]
        ];
    }

    public function init()
    {
        parent::init(); // TODO: Change the autogenerated stub
        if (Yii::$app->user->isGuest) {
            return $this->goHome();
        }
        $this->globalBaseData();
    }

    /**
     * 初始化数据
     */
    public function globalBaseData()
    {
        // 选中菜单
        AdminRule::instance()->setActiveMenu();
        //面包屑导航
        AdminRule::instance()->setBreadcrumb();
    }

    /**
     * 获取模型
     * @param string $controller
     * @return object
     * @throws \yii\base\InvalidConfigException
     */
    public function getModel($controller = '')
    {
        if (!$controller) {
            $controller = $this->_model;
        }
        if (!$controller) {
            $controller = $this->id;

        }
        if (class_exists('backend\models\\' . $this->parseModel($controller))) {
            $model = Yii::createObject('backend\models\\' . $this->parseModel($controller));
        } else {
            $model = (new \yii\db\Query())->from($this->parseTable($controller));
        }

        return $model;
    }

    /**
     * 通过控制器解析model
     * @param $controller
     * @return string
     */
    public function parseModel($controller)
    {
        if (strpos($controller, '-')) {
            $controllerMap = explode('-', $controller);
            foreach ($controllerMap as &$val) {
                $val = ucfirst($val);
            }
            unset($val);
            $controller = implode('', $controllerMap);
        } else {
            $controller = ucfirst($controller);
        }
        return $controller;
    }

    /**
     * 解析表名
     * @param $controller
     * @return string|string[]
     */
    public function parseTable($controller)
    {
        if (!$controller) {
            $controller = Yii::$app->controller;
        }
        $table = str_replace('-', '_', $controller);
        return Yii::$app->db->tablePrefix . $table;
    }

    /**
     * 自动过滤模型字段
     * @param $model
     * @param array $param
     * @return array
     */
    public function search($model, $param = [])
    {
        $map = [];
        $params = array_merge(Yii::$app->request->get(), $param);
        if ($model instanceof Query) {
            $tableName = $model->from[0];
        } else {
            $tableName = $model::tableName();
        }
        $db = Yii::$app->db;
        $column = $db->getTableSchema($tableName)->columns;
        foreach ($params as $key => $val) {
            if ($val !== "" && array_key_exists($key, $column)) {
                $map[$key] = $val;
            }
        }
        return $map;
    }

    /**
     * 获取列表数据
     * @param $model
     * @param $map
     */
    public function getList($model, $map)
    {
        //通过过滤器指定模型
        if (isset($map['_model'])) {
            $model = $map['_model'];
        }
        if (method_exists($model, 'find')) {
            $model = $model::find();
        }
        if (isset($map['_func']) && ($map['_func'] instanceof \Closure)) {
            call_user_func($map['_func'], $model);
        }
        //排序字段 默认是id
        $order = $map['_order'] ?? 'id';
        $sort = $map['_sort'] ?? 'desc';
        $order_by = $order ? "{$order} {$sort}" : false;
        if (isset($map['_order_by'])) {
            $order_by = $map['_order_by'];
        }
        // 查询字段
        $field = '*';
        if (isset($map['_field'])) {
            $field = $map['_field'];
        }
        //分页
        if (isset($map['_paginate'])) {
            $paginate = $map['_paginate'];

        }
        //过滤多余字段
        foreach ($map as $key => $val) {
            if (strncmp($key, '_', 1) === 0) {
                unset($map[$key]);
            }
        }
        $query = $model->select($field)->where($map)->orderBy($order_by);
        $currentPage = Yii::$app->request->get('currentPage') ?? 1;
        $pageSize = Yii::$app->request->get('pageSize') ?? Yii::$app->params['pageSize'];
        $count = $query->count();
        if (empty($paginate) || $paginate !== 'false') {
            $query->offset($pageSize * ($currentPage - 1))->limit($pageSize);
        }
        if (method_exists($model, 'asArray')) {
            $query->asArray();
        }
        $tableData = $query->all();
        if (method_exists($this, 'afterFilter')) {
            $this->afterFilter($tableData);
        }
        $this->data['currentPage'] = $currentPage;
        $this->data['pageSize'] = $pageSize;
        $this->data['count'] = $count;
        $this->data['tableData'] = json_encode($tableData);
        Yii::$app->view->params['data'] = $this->data;
        return $this->data;
    }

    /**
     * 成功返回数据
     * @param array $data
     * @param string $message
     * @param int $code
     * @return array
     */
    public function success($data = [], $message = '', $code = 0)
    {
        return $this->apiJson($data, $message, $code);
    }

    /**
     * 失败返回数据
     * @param string $message
     * @param int $code
     * @param array $data
     * @return array
     */
    public function error($message = '', $code = 1, $data = [])
    {
        return $this->apiJson($data, $message, $code);
    }

    /**
     * json数据
     * @param array $data
     * @param string $message
     * @param int $code
     * @return array
     */
    public function apiJson(array $data, string $message, int $code)
    {
        Yii::$app->response->format = Response::FORMAT_JSON;

        /** @var  $result */
        $result = [
            'code' => strval($code),
            'message' => trim($message),
            'data' => $data ? ArrayHelper::toArray($data) : new \stdClass(),
        ];
        return $result;
    }
}